package com.odianyun.springboottest.startup.config;

import com.odianyun.project.exception.I18nException;
import com.odianyun.project.exception.VisibleException;
import com.odianyun.project.message.CodeEnum;
import com.odianyun.project.message.ICodeMessage;
import com.odianyun.project.model.vo.ObjectResult;
import com.odianyun.project.model.vo.Result;
import com.odianyun.project.util.ValidUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.io.IOException;

/**
 * @description:
 * @author: EDZ
 * @time: 16:35
 * @date: 2021/7/25
 */
@RestControllerAdvice
public class GlobalExceptionHandle {
    private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandle.class);

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public Object handleValidException(MethodArgumentNotValidException e, HttpServletRequest req, HttpServletResponse response) {
        String validMsg = ValidUtils.extractErrorMessage(e);
        this.logger.debug("MethodArgumentNotValidException---", e);
        this.logger.info(validMsg);
        return new Result(CodeEnum.VALIDATE_ERROR.getCode(), validMsg);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public Object handleValidException(ConstraintViolationException e, HttpServletRequest req, HttpServletResponse response) {
        String validMsg = ValidUtils.extractErrorMessage(e);

        logger.debug("ConstraintViolationException---", e);
        logger.info(validMsg);

        if (validMsg != null) {
            return new Result(CodeEnum.VALIDATE_ERROR.getCode(), validMsg);
        }

        return new Result(CodeEnum.VALIDATE_ERROR);
    }

    @ExceptionHandler(VisibleException.class)
    @ResponseBody
    public Object handleVisibleException(VisibleException e, HttpServletRequest req, HttpServletResponse response) {
        logger.debug("VisibleException---", e);
        logger.error(e.getMessage() + (e.getCause() != null && StringUtils.isNotBlank(e.getCause().getMessage())?
                " caused by: " + e.getCause().getMessage(): ""));

        if (e instanceof I18nException) {
            I18nException ie = (I18nException) e;
            ICodeMessage msg = ie.getMsg();
            if (msg != null) {
                return new Result(msg.getCode(), e.getMessage());
            }
        }

        if (e.getData() != null) {
            return new ObjectResult<>(CodeEnum.SERVICE_ERROR.getCode(), e.getMessage(), e.getData());
        }

        return new Result(CodeEnum.SERVICE_ERROR.getCode(), e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public Result handleException(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException {
        logger.info("服务异常", e);
        return new Result(CodeEnum.ERROR.getCode(), CodeEnum.ERROR.getMessage());
    }

}
